package retail.dao.impl;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import HibernateBeans.CustomerDetails;
import HibernateBeans.Customer_Products;
import HibernateBeans.Invoice;
import HibernateBeans.ProductDetails;
import HibernateBeans.RepDetails;
import HibernateBeans.UserRoles;
import HibernateBeans.Users;
import retail.dao.CustomerDao;

public class CustomerDaoImpl implements CustomerDao {
	private SessionFactory sessionFactory;

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@Override
	public boolean addCustomer(CustomerDetails customer) {
		if(customer.getUser_id()==null){
			String nc=getNextCustomerID();
			customer.setUser_id(nc);
		}
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		session.save(customer);
		tx.commit();
		return tx.wasCommitted();
	}

	@Override
	public CustomerDetails getCustomer(String username) {
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		Criteria criteria = session.createCriteria(CustomerDetails.class);
		criteria.add(Restrictions.eq("user.user_name", username));
		List<CustomerDetails> lc = criteria.list();
		tx.commit();
		session.close();
		if (lc.isEmpty())
			return null;
		else
			return lc.get(0);
	}

	@Override
	public List<CustomerDetails> findAllCustomer() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public List<ProductDetails> getProducts(String username) {		
		Session session =sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		Criteria criteria =session.createCriteria(Customer_Products.class,"cp");
		criteria.createAlias("cp.custd", "c");
		criteria.createAlias("c.user", "user");
		criteria.add(Restrictions.eq("user.user_name", username));
		List<Customer_Products> cp=criteria.list();
		List<ProductDetails> lp=new ArrayList<ProductDetails>();
		for(Customer_Products c: cp){
			Hibernate.initialize(c.getProdd());
			lp.add(c.getProdd());
		}
		tx.commit();
		session.close();
		return lp;
	}

	@Override
	public List<ProductDetails> getAllProducts() {
		
		return sessionFactory.getCurrentSession().createCriteria(ProductDetails.class).list();
	}

	@Override
	public List<ProductDetails> getUpgrades(ProductDetails product) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		Criteria criteria=session.createCriteria(ProductDetails.class);
		criteria.add(Restrictions.gt("cost", product.getCost()));
		criteria.add(Restrictions.like("product_type", product.getProduct_type()));
		return criteria.list();
	}

	@Override
	public boolean upgrade(String username, ProductDetails product) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		Criteria criteria=session.createCriteria(Customer_Products.class,"cp");
		criteria.createAlias("cp.custd", "c");
		criteria.createAlias("c.user", "user");
		criteria.createAlias("cp.prodd", "p");
		criteria.add(Restrictions.eq("user.user_name",username));
		criteria.add(Restrictions.like("p.product_type", product.getProduct_type()));
		List<Customer_Products> lp=criteria.list();
		if(!lp.isEmpty()){
			Customer_Products customerProducts=lp.get(0);
			customerProducts.setProdd(product);
			session.update(customerProducts);
		}
		
		tx.commit();
		return tx.wasCommitted();
		try {
			tx.commit();
		} catch (HibernateException e) {
			tx.rollback();
			return false;
		}
		session.close();
		return true;
	}

	@Override
	public ProductDetails getProduct(String pid) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		ProductDetails p=(ProductDetails) session.get(ProductDetails.class, pid);
		System.out.println(p);
		tx.commit();
		session.close();
		return p;
	}

	@Override
	public Invoice getCurrentInvoice(String username) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		Criteria criteria=session.createCriteria(Invoice.class,"inv");
		criteria.createAlias("inv.custd", "c");
		criteria.createAlias("c.user", "user");
		criteria.add(Restrictions.eq("user.user_name", username));
		criteria.add(Restrictions.ge("due_date", new Date(new java.util.Date().getTime())));
		List<Invoice> li=criteria.list();
		tx.commit();
	
		if(li.isEmpty())
		return null;
		return li.get(0);
	}

	@Override
	public String getNextCustomerID() {
		Session session=sessionFactory.getCurrentSession();
		Criteria criteria=session.createCriteria(CustomerDetails.class);
		criteria.setProjection(Projections.max("user_id"));
		String customerValue=(String) criteria.uniqueResult();
		int maxC=Integer.parseInt(customerValue.substring(1));
		String nc=String.format("C%03d",++maxC);
		return nc;
	}

	@Override
	public CustomerDetails getUser(String uid) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		CustomerDetails cd=(CustomerDetails) session.get(CustomerDetails.class, uid);
		tx.commit();
		session.close();
		return cd;
	}




	@Override
	public boolean resetPassword(Users user) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		session.update(user);
		tx.commit();
		return tx.wasCommitted();
	}

	@Override
	public boolean payBills(Invoice invoice, double amount) {
		System.out.println(invoice);
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		double current_amount=invoice.getBill_amount();
		current_amount-=amount;
		invoice.setBill_amount(current_amount);
		session.update(invoice);
		tx.commit();
		return tx.wasCommitted();
	}

	@Override
	public boolean registerUser(String userID, Users user) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		CustomerDetails cd=(CustomerDetails) session.get(CustomerDetails.class, userID);
		cd.setUser(user);
		session.update(cd);
		tx.commit();
		return tx.wasCommitted();
	}

	@Override
	public boolean removeProduct(String username, String pid) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		Criteria criteria=session.createCriteria(Customer_Products.class,"cp");
		criteria.createAlias("cp.custd", "cd");
		criteria.createAlias("cd.user", "user");
		criteria.createAlias("cp.prodd", "p");
		criteria.add(Restrictions.eq("user.user_name", username));
		criteria.add(Restrictions.eq("p.pid", pid));
		Customer_Products cp=(Customer_Products) criteria.uniqueResult();
		session.delete(cp);
		tx.commit();
		return tx.wasCommitted();
	}
	@Override
	public int countUser(String username,String userid){
		//Hibernate code to get #users with same uname
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		Users user=(Users) session.get(Users.class, username);
		CustomerDetails c=(CustomerDetails) session.get(CustomerDetails.class, userid);
		RepDetails r     =(RepDetails)      session.get(RepDetails.class     , userid);
		tx.commit();
		if (user==null|((c==null)&(r==null))){
			return 0;
		}
		else{
			return 1;
		}
	}
	
	public String getSecurityQuestion(String uid){
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		CustomerDetails SQ=(CustomerDetails) session.get(CustomerDetails.class, uid);
		String SecurityQuestion=SQ.getSecurity_question();
		tx.commit();
		return SecurityQuestion;
	}
	
	public boolean checkSecurityAnswer(String uid,String answer,String fname, String lname,String password){
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		CustomerDetails SQ=(CustomerDetails) session.get(CustomerDetails.class, uid);
		String SecurityAnswer=SQ.getSecurity_answer();
		String fn=			  SQ.getFirst_name();
		String ln=			  SQ.getLast_name();
		String un=			  SQ.getUser().getUser_name();
		boolean correct;
		if((answer.equals(SecurityAnswer))&(fn.equals(fname))&(ln.equals(lname)))
		{
			Users USER=(Users) session.get(Users.class, un);
			USER.setUser_pass(password);
			correct=true;
		}
		else
		{
			correct=false;
		}
		tx.commit();
		return correct;
	}
	
	public boolean checkDetailsRep(String uid,String fname,String lname, String email,String password){
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		RepDetails SQ=(RepDetails) session.get(RepDetails.class, uid);
		String fn=			  SQ.getFirst_name();
		String ln=			  SQ.getLast_name();
		String em=            SQ.getEmail();
		String un=			  SQ.getUser().getUser_name();
		
		boolean correct;
		if((em.equals(email))&(fn.equals(fname))&(ln.equals(lname)))
		{
			Users USER=(Users) session.get(Users.class, un);
			USER.setUser_pass(password);
			correct=true;
		}
		else
		{
			correct=false;
		}
		tx.commit();
		return correct;
	}

	@Override
	public boolean addCustomerProduct(Customer_Products customerProduct) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		session.save(customerProduct);
		tx.commit();
		return tx.wasCommitted();
	}

	@Override
	public RepDetails getRepDetails(String userID) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		RepDetails rd = (RepDetails) session.get(RepDetails.class, userID);
		tx.commit();
		return rd;
	}

	@Override
	public boolean addUser(Users user, String role) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
//		try {
			session.save(user);
			UserRoles ur=new UserRoles(user,role);
			System.out.println(ur.getRole());
			session.save(ur);
			tx.commit();
/*		} catch (HibernateException e) {
			tx.rollback();
			return false;
		}*/
		return tx.wasCommitted();
	}

	@Override
	public boolean updateCustomer(CustomerDetails customerDetails) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		try {
			session.update(customerDetails);
			tx.commit();
		} catch (HibernateException e) {
			return false;
		}
		return tx.wasCommitted();
	}

	@Override
	public boolean updateRep(RepDetails repDetails) {
		Session session=sessionFactory.getCurrentSession();
		Transaction tx=session.beginTransaction();
		try {
			session.update(repDetails);
			tx.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return tx.wasCommitted();
	}
}
